package com.infore.exchange.main.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.infore.common.base.Msg;
import com.infore.common.base.ResultUtil;
import com.infore.common.enums.ScheduleEnum;
import com.infore.common.exception.MyException;
import com.infore.common.model.entity.exchange.TJobInfo;
import com.infore.common.model.entity.exchange.TJobTaskInfo;
import com.infore.common.utils.UUIDGenerator;
import com.infore.exchange.main.dao.TJobInfoMapper;
import com.infore.exchange.main.dao.TJobTaskInfoMapper;
import com.infore.exchange.main.quartz.CronTaskRegistrar;
import com.infore.exchange.main.quartz.SchedulingRunnable;
import com.infore.exchange.main.service.TJobInfoService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.infore.exchange.main.service.TJobTaskInfoService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 作业信息表 服务实现类
 * </p>
 *
 * @author lijh
 * @since 2023-02-13
 */
@Service
public class TJobInfoServiceImpl extends ServiceImpl<TJobInfoMapper, TJobInfo> implements TJobInfoService {

    @Autowired
    private TJobInfoMapper jobInfoMapper;
    @Autowired
    private TJobTaskInfoMapper jobTaskInfoMapper;

    @Autowired
    private TJobTaskInfoService TJobTaskInfoService;

    @Autowired
    private CronTaskRegistrar cronTaskRegistrar;

    @Override
    public boolean updateJobStateById(String jobId, Integer jobStatus) {
        jobInfoMapper.updateJobStateById(jobId,jobStatus);
        return true;
    }

    @Override
    public List<TJobInfo> queryHaveTaskJobInfo(String jobId, Integer jobStatus,Integer taskStatus) {
        List<TJobInfo> jobs = jobInfoMapper.queryHaveTaskJobInfo(jobId, jobStatus);
        return jobs;
    }

    @Override
    public boolean updateExecTime(String jobId, Date preTime, Date nextTime) {
        jobInfoMapper.updateExecTime(jobId,preTime, nextTime);
        return true;
    }


    @Override
    public boolean deleteJob(String jobId){
        this.deleteById(jobId);

        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("job_id", jobId);
        jobTaskInfoMapper.deleteByMap(columnMap);
        return true;
    }

    @Override
    @Transactional(rollbackFor={Exception.class})
    public Msg<Object> addOrEdit(TJobInfo tjobinfo){
        /**
         * 指定作业执行方法
         */
        tjobinfo.setBeanName(ScheduleEnum.EX_JOB.getBeanName());
        tjobinfo.setMethodName(ScheduleEnum.EX_JOB.getMethodName());

        boolean flag = false;
        CronExpression cronExpression = null;
        try {
            cronExpression = new CronExpression(tjobinfo.getCronSchedule());
        } catch (ParseException e) {
            e.printStackTrace();
            throw new MyException("500","cron表达式格式异常："+tjobinfo.getCronSchedule(),e.getMessage());
        }
        if(StringUtils.isEmpty(tjobinfo.getJobId()) ){
            //新增
            Wrapper<TJobInfo> wrapper = new EntityWrapper<TJobInfo>();
            wrapper.eq("job_name", tjobinfo.getJobName());
            List<TJobInfo> entityList = this.selectList(wrapper);
            if(entityList.size()>0) {
                return ResultUtil.error("作业名称已存在");
            }
            String jobId = UUIDGenerator.generator();
            tjobinfo.setJobId(jobId);
            tjobinfo.setJobState(1);
            tjobinfo.setCreateTime(new Date());
            tjobinfo.setUpdateTime(new Date());
            Date nextDate = cronExpression.getTimeAfter(new Date());
            tjobinfo.setNextExecTime(nextDate);
            flag = this.insert(tjobinfo);
            if(flag){
                bindTasks(tjobinfo);
                SchedulingRunnable task = new SchedulingRunnable(tjobinfo.getBeanName(), tjobinfo.getMethodName(), tjobinfo.getJobId());
                if(!cronTaskRegistrar.hasCronTask(task)){
                    cronTaskRegistrar.addCronTask(task, tjobinfo.getCronSchedule());
                }
            }
            return ResultUtil.successData(tjobinfo);
        }else{

            TJobInfo targetJob = this.selectById(tjobinfo.getJobId());
            CopyOptions copyOptions = new CopyOptions();
            copyOptions.setIgnoreNullValue(true);
            BeanUtil.copyProperties(tjobinfo,targetJob,copyOptions);
            targetJob.setUpdateTime(new Date());
            if(targetJob.getJobState()==1){
                Date nextDate = cronExpression.getTimeAfter(new Date());
                targetJob.setNextExecTime(nextDate);
            }
            flag = this.updateById(targetJob);
            if(flag){
                bindTasks(targetJob);
                SchedulingRunnable task = new SchedulingRunnable(targetJob.getBeanName(), targetJob.getMethodName(), targetJob.getJobId());
                if(cronTaskRegistrar.hasCronTask(task)){
                    cronTaskRegistrar.removeCronTask(task);
                }
                if(targetJob.getJobState()==1){
                    cronTaskRegistrar.addCronTask(task, targetJob.getCronSchedule());
                }
            }
            return ResultUtil.successData(targetJob);
        }

    }

    /**
    * @Deacription 绑定任务
    * @MethodName bindTasks
    * @param tjobinfo
    * @return
    * @Author lijianhua
    * @Date 2023/3/3 14:46
    **/
    private void bindTasks(TJobInfo tjobinfo) {
        List<String> taskIds= Arrays.asList(tjobinfo.getTaskIdsStr().split(","));
        List<TJobTaskInfo> list = new ArrayList<>();
        for (String taskId:taskIds) {
            TJobTaskInfo entity = new TJobTaskInfo();
            entity.setId(UUIDGenerator.generator());
            entity.setJobId(tjobinfo.getJobId());
            entity.setTaskId(taskId);
            list.add(entity);
        }
        //清空之前绑定的数据
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("job_id", tjobinfo.getJobId());
        TJobTaskInfoService.deleteByMap(columnMap);
        TJobTaskInfoService.insertBatch(list);
    }


    @Override
    public List<String> cronParser(String cronSchedule) throws ParseException {
        //获取最近5次执行时间
        CronExpression cronExpression = new CronExpression(cronSchedule);
        Date dateOne = cronExpression.getTimeAfter(new Date());
        Date dateTwo = cronExpression.getTimeAfter(dateOne);
        Date dateThree = cronExpression.getTimeAfter(dateTwo);
        Date dateFour = cronExpression.getTimeAfter(dateThree);
        Date dateFive = cronExpression.getTimeAfter(dateFour);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeOne = df.format(dateOne);
        String timeTwo = df.format(dateTwo);
        String timeThree = df.format(dateThree);
        String timeFour = df.format(dateFour);
        String timeFive = df.format(dateFive);

        List<String> result = new ArrayList<String>();
        result.add("最近5次运行时间：");
        result.add(timeOne);
        result.add(timeTwo);
        result.add(timeThree);
        result.add(timeFour);
        result.add(timeFive);
        return result;
    }
}
